import { useEffect, useState, useRef, Key, useCallback, useImperativeHandle, forwardRef } from 'react';
import * as echarts from 'echarts';
import { Dropdown, Menu, Modal, message, Breadcrumb, Typography } from 'antd';
import BizBody from '@inbiz/basic/BizBody';
import FilterModal from '@inbiz/basic/BiFilterModal';
import { observer } from '@formily/react';
import { getMessage, TextWidget } from '@inbiz/react';
import { getEditor, InbizIcon, useEvents, singleTimeOut } from '@inbiz/utils';
import { useInbizRouter } from '@inbiz/hooks';
import {
  getTitleConfig,
  getLegendConfig,
  getLabelConfig,
} from '../../../BiBarMap/preview/web/utils';
import { getData as serviceData } from './service';
import api from './api';
import './style.less';
import type { ObjProps } from './data.d';
import { GlobalRegistry } from '@inbiz/core';
type EChartOption = echarts.EChartOption;
type Chart = echarts.ECharts;

const { Text } = Typography;
const isEditor = getEditor();
const App = observer((props: ObjProps) => {
  const {
    ref,
    axis,
    axisSort = {},
    leftValue,
    rightValue = [],
    mapLegend = {},
    filter = [],
    detailView,
    detailViewHref,
    xaxisTitle,
    xaxisUnit,
    yxisTitleLeft,
    yxisUnitRight,
    yxisTitleRight,
    yxisUnitLeft,
    dataLabel,
    titlePosition,
    legendPosition,
    borderColor,
    mapBackground,
    borderWidth,
    mapdata,
    colorPattern,
    title,
    maptitleColor,
    titleFontSize,
    ifShowMapLegend = true,
    style = {
      height: '300px',
      padding: '0px 0px 0px 0px',
    },
    axises = ['horizontal', 'vertical'],
    labelColor,
    legendColor,
    axisesColor,
  } = props;

  const [configEvents] = useEvents(props.callBackEvents, props.emit);
  const chartRef = useRef<Chart>();
  const mydownValues = useRef<any>([]);
  const [showChildMap, $showChildMap] = useState(false);
  const [showFilterModal, $showFilterModal] = useState(false);
  const [myFilter, $myFilter] = useState(filter);
  const [level, $level] = useState<any>(0); // 没什么用, 就是为了页面渲染
  const [noData, $noData] = useState(true);
  const [currentDownvalue, $currentDownvalue] = useState<any>({});
  const history = useInbizRouter();
  const $option = useRef()
  const getData = useCallback(async (params: object) => {
    const newParams = (await configEvents.current?.onParams?.(params)) || params;
    const data = await (configEvents.current?.onRequest || serviceData)(newParams as any)
    return await configEvents.current?.onData?.(data) || data
  }, []);

  useEffect(() => {
    setmapOptions($option?.current?.optionData, $option?.current?.chart)
  }, [GlobalRegistry.getDesignerLanguage()])


  // 地图跳转
  const handleMapClick = (params) => {
    props.emit?.('onClick', params);
    if (isEditor) {
      return;
    }
    if (detailView == 'skip' && detailViewHref) {
      if (detailViewHref.startsWith('http')) {
        window.open(detailViewHref);
      } else if (detailViewHref.startsWith('www')) {
        window.open(`https://${detailViewHref}`);
      } else {
        history.push(detailViewHref);
      }
    }
  };

  // 设置地图配置
  const setmapOptions = async (
    optionData: {
      legend?: never[] | undefined;
      series: any;
      xAxis: any;
      legendRight?: never[] | undefined;
    },
    chart: { clear: () => void; setOption: (arg0: EChartOption) => void },
  ) => {
    const { legend = [], series, xAxis, legendRight = [] } = optionData;
    chart.clear();
    let _series = series;
    _series = _series?.map((item: { label: any }) => {
      return {
        ...item,
        label: {
          ...item?.label,
          color: labelColor
        },
      };
    });
    // 指定图表的配置项和数据
    let yAxisObj = {};

    let axisLabelobj = {
      textStyle: {
        color: axisesColor || '#999',
      }
    };

    let nameTextStyleObj = {
      color: axisesColor || '#999',
    };

    if (leftValue && leftValue.length > 0 && rightValue && rightValue.length > 0) {
      yAxisObj = [
        {
          name: yxisUnitLeft ? `${yxisTitleLeft}(${yxisUnitLeft})` : yxisTitleLeft,
          nameTextStyle: nameTextStyleObj,
          show: axises?.includes('vertical'),
          axisLabel: axisLabelobj,
        },
        {
          name: yxisUnitRight ? `${yxisTitleRight}(${yxisUnitRight})` : yxisTitleRight,
          nameTextStyle: nameTextStyleObj,
          alignTicks: true,
          show: axises?.includes('vertical'),
          axisLabel: axisLabelobj,
        },
      ];
    } else if (leftValue && leftValue.length > 0) {
      yAxisObj = {
        name: yxisUnitLeft ? `${yxisTitleLeft}(${yxisUnitLeft})` : yxisTitleLeft,
        nameTextStyle: nameTextStyleObj,
        show: axises?.includes('vertical'),
        axisLabel: axisLabelobj,
      };
    } else if (rightValue && rightValue.length > 0) {
      yAxisObj = [
        {
          show: false,
        },
        {
          name: yxisUnitRight ? `${yxisTitleRight}(${yxisUnitRight})` : yxisTitleRight,
          nameTextStyle: nameTextStyleObj,
          alignTicks: true,
          position: 'right',
          show: axises?.includes('vertical'),
          axisLabel: axisLabelobj,
        },
      ];
    }
    const option: EChartOption = {
      title: title.status
        ? {
          ...getTitleConfig(titlePosition, getMessage(title.value)),
          textStyle: {
            color: maptitleColor || '#000',
            fontSize: titleFontSize || 20,
          },
        }
        : undefined,
      color: colorPattern.colorArray,
      tooltip: {
        trigger: 'axis',
        // formatter: getLabelConfig(dataLabel),
      },
      textStyle: {
        color: legendColor || '#999',
      },
      // grid: {
      //   left: 120,
      //   right: 120,
      // },
      legend: {
        ...getLegendConfig(legend.concat(legendRight), legendPosition, titlePosition),
        show: ifShowMapLegend !== false,
        textStyle: {
          color: legendColor || '#999',
        },
      },
      xAxis: {
        name: xaxisUnit ? `${xaxisTitle}(${xaxisUnit})` : xaxisTitle,
        nameLocation: 'end',
        nameTextStyle: {
          align: 'right',
          verticalAlign: 'top',
          lineHeight: 60,
          color: axisesColor || '#999',
        },
        data: xAxis,
        show: axises?.includes('horizontal'),
        axisLabel: axisLabelobj,
      },
      yAxis: yAxisObj,
      series: _series,
    };
    // 使用刚指定的配置项和数据显示图表。
    const _option = (await configEvents.current?.onEchartsOptions?.(option)) || option;
    if (isEditor) {
      singleTimeOut(() => {
        let chartDom = document.getElementById(props?.controlId);
        if (chartRef.current) {
          chartRef.current.resize({
            width: chartDom?.clientWidth,
            height: chartDom?.clientHeight,
          });
        }
        chart.setOption(_option);
      }, 0, props?.controlId);
    } else {
      singleTimeOut(() => {
        let chartDom = document.getElementById(props?.controlId);
        if (chartRef.current) {
          chartRef.current.resize({
            width: chartDom?.clientWidth,
            height: chartDom?.clientHeight,
          });
        }
        chart.setOption(_option);
      }, 600, props?.controlId);
    };
  };

  // 查询地图数据
  const getMapData = (
    { newFilter = [], downValues }: { newFilter?: any; downValues?: any },
    chart: echarts.EChartsType | undefined,
  ) => {
    getData({
      soureOutId: mapdata.dataName.OutId,
      dbSearch: {
        xAxis: axis[0] ?? {},
        countColumn: leftValue,
        countColumnRight: rightValue,
        legend: mapLegend[0],
        conditions: newFilter && newFilter.length > 0 ? newFilter : filter,
        downValues: downValues && downValues.length > 0 ? downValues : [],
        sort: axisSort[0],
      },
    })
      .then((res) => {
        if (res && res.xAxis) {
          const { series = [], seriesRight } = res;
          const seriesArr1 = series?.map((item: any) => ({
            ...item,
            type: 'line',
            label: {
              show: true,
              formatter: getLabelConfig(dataLabel),
            },
          }));
          const seriesArr2 = seriesRight
            ? seriesRight.map((item: any) => ({
              ...item,
              type: 'line',
              yAxisIndex: 1,
              label: {
                show: true,
                formatter: getLabelConfig(dataLabel),
              },
            }))
            : [];

          setmapOptions(
            {
              ...res,
              series: seriesArr1.concat(seriesArr2),
            },
            chart!,
          );
          $option.current = {
            optionData: {
              ...res,
              series: seriesArr1.concat(seriesArr2),
            },
            chart,
          };
          $noData(false);
        } else {
          chart?.clear();
          $noData(true);
        }
      })
      .catch((e) => {
        chart?.clear();
        $noData(true);
      });
  };

  // 下探
  const handleDown = (downValue: { Legend: any; XAxis: any }, type?: boolean | undefined) => {
    if (axis.length > 0 && axis[0]?.DownColumns.length > 0) {
      if (mydownValues.current.length > 4) {
        return message.warn(getMessage('BiLineMap.topsFive'));
      }
      if (mydownValues.current.length >= axis[0].DownColumns.length) {
        return;
      }
      let downValues = [];
      if (type) {
        mydownValues.current = [...mydownValues.current, downValue];
        $level((lev: number) => lev + 1);
        downValues = mydownValues.current;
      } else {
        if (currentDownvalue.XAxis) {
          $level((lev: number) => lev + 1);
          mydownValues.current = [...mydownValues.current, currentDownvalue];
          downValues = mydownValues.current;
        } else {
          return;
        }
      }
      $showChildMap(true);
      getMapData({ downValues }, chartRef.current);
      $currentDownvalue({});
    } else {
      message.info(getMessage('BiLineMap.probeField'));
    }
  };
  // 图表右击事件
  const handleItemClick = (e: { key: any }) => {
    if (isEditor) {
      return;
    }
    switch (e.key) {
      case '1':
        handleMapClick();
        break;
      case '2':
        handleDown(mydownValues.current);
        break;
      default:
        break;
    }
  };
  const menu = (
    <Menu
      onClick={handleItemClick}
      items={[
        {
          key: '1',
          label: (
            <span>
              <TextWidget>BiLineMap.jumpDetail</TextWidget>
            </span>
          ),
          disabled: !detailViewHref || detailView != 'skip',
        },
        {
          key: '2',
          label: (
            <span>
              <TextWidget>BiLineMap.probe</TextWidget>
            </span>
          ),
          disabled:
            axis[0]?.DownColumns.length > 5 ||
            axis[0]?.DownColumns.length == 0 ||
            mydownValues.current.length == axis[0]?.DownColumns.length,
        },
      ]}
    />
  );
  const onCancel = () => {
    $showFilterModal(false);
  };
  const onOk = async () => {
    if (ref.current && ref.current?.submit) {
      const newFilter = await ref.current?.submit();
      const downValues = mydownValues.current;
      $myFilter(newFilter);
      getMapData({ newFilter, downValues }, chartRef.current);
      onCancel();
    }
  };

  // 返回
  const handleReturn = (index: number) => {
    if (isEditor) {
      return;
    }
    const downValues = mydownValues.current.slice(0, index);
    mydownValues.current = mydownValues.current.slice(0, index);
    $level((lev: number) => lev - 1);
    getMapData({ newFilter: myFilter, downValues }, chartRef.current);
    if (downValues == 0) {
      $showChildMap(false);
    }
  };
  const $domRef = useRef<HTMLDivElement>(null);
  // 初始化图表
  useEffect(() => {
    if ($domRef.current) {
      const chart = echarts.init($domRef.current);
      chart.on('click', 'series', handleMapClick);
      //@ts-ignore
      chart.on('dblclick', 'series', (event: { name: any; seriesName: any }) => {
        if (isEditor || !event.name) {
          return;
        }
        handleDown(
          {
            Legend: event.seriesName,
            XAxis: event.name,
          },
          true,
        );
      });
      //@ts-ignore
      chart.on('contextmenu', 'series', (event: { name: any; seriesName: any }) => {
        if (isEditor || !event.name) {
          return;
        }

        $currentDownvalue({
          Legend: event.seriesName,
          XAxis: event.name,
        });
      });
      chartRef.current = chart;
    }
  }, []);

  useEffect(() => {
    if (
      mapdata &&
      mapdata.dataName &&
      ((leftValue && leftValue.length > 0) || (rightValue && rightValue.length > 0)) &&
      axis &&
      axis.length > 0
    ) {
      getMapData({ newFilter: [] }, chartRef.current);
      $showChildMap(false);
      mydownValues.current = [];
    } else {
      chartRef.current?.clear();
      $noData(true);
    }
  }, [props]);


  useImperativeHandle(
    ref,
    () => api(configEvents, {
      loadData: (data: any) => {
        setmapOptions(data, chartRef.current!)
      }
    })
    ,
    [props, chartRef.current, mydownValues.current, myFilter],
  );

  return (
    <BizBody
      style={{
        height: 'inherit',
        ...style,
      }}
    >
      <div
        className="inbiz-line"
        style={{
          // width: '100%',
          ...mapBackground.style,
          backgroundSize: '100%, 100%',
          position: 'relative',
          height: '100%',
        }}
      >
        {showChildMap && (
          <div
            style={{
              position: 'absolute',
              top: 16,
              left: 16,
              zIndex: 99999,
              display: 'flex',
              alignItems: 'center',
              height: 24,
              color: maptitleColor || '#000',
            }}
          >
            {/* <a onClick={() => handleReturn(mydownValues.current.length - 1)}>
                <TextWidget>BiLineMap.back</TextWidget>
              </a> */}
            <InbizIcon
              type="icon-inbiz_other-return"
              onClick={() => handleReturn(mydownValues.current.length - 1)}
              style={{ position: 'absolute' }}
            />
            <Breadcrumb className={`inbiz-bar-breadcrumb`} separator={<span style={{ color: maptitleColor || '#000' }}>/</span>}>
              {mydownValues.current.map(
                (item: { XAxis: {} | null | undefined }, index: Key | null | undefined) => (
                  <Breadcrumb.Item key={index} onClick={() => handleReturn(index + 1)}>
                    <Text title={item.XAxis} ellipsis style={{ cursor: 'pointer', color: maptitleColor || '#000', }}>
                      {item.XAxis.length > 10 ? `${item.XAxis.slice(0, 10)}...` : item.XAxis}
                    </Text>
                  </Breadcrumb.Item>
                ),
              )}
            </Breadcrumb>
          </div>
        )}
        <div
          className={`inbiz-line-iconParent`}
          style={{ height: noData ? 0 : '100%', border: `${borderWidth}px solid ${borderColor}` }}
        >
          <Dropdown overlay={menu} trigger={['contextMenu']}>
            <div style={{ width: '100%', height: '100%' }} ref={$domRef} id={props?.controlId} />
          </Dropdown>
          {filter.length > 0 && (
            <div
              className={`icon`}
              onClick={(e) => {
                if (isEditor) {
                  return;
                }
                e.stopPropagation();
                $showFilterModal(true);
              }}
            >
              <InbizIcon type="icon-a-shaixuantubiao" className="iconicon" />
            </div>
          )}
        </div>
        {noData && (
          <div className="inbiz-line-nodataContainer">
            <InbizIcon style={{ fontSize: 120 }} type="icon-inbiz-BI-queshengtu" />
            <div style={{ color: '#c2c2c2' }}>
              <TextWidget>BiLineMap.addData</TextWidget>
            </div>
          </div>
        )}
      </div>
      <Modal
        title={getMessage('BiLineMap.filterCondition')}
        visible={showFilterModal}
        onCancel={onCancel}
        onOk={onOk}
        getContainer={false}
        destroyOnClose
      >
        <FilterModal list={myFilter} active={0} refs={ref} />
      </Modal>
    </BizBody>
  );
});

export default App;
export { App as LineMap };
